#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, os
from PyQt4 import QtCore, QtGui
from libASFX import *
from dialog_new_AE import dialog_new_EA
from dialog_edit_AE import dialog_Edit_EA
from dialog_new_relation import dialog_new_relation
from dialog_new_relation_type import dialog_new_relation_type


class MyCFTreeWidgetItem(AE, QtGui.QTreeWidgetItem):
	def __init__(self,libmyCF, ae):
		QtGui.QTreeWidgetItem.__init__(self, 0)
		
		#name (depending on the selected language), definition, source, curator)
		if libmyCF.ontology.translation =="English translation" :
			AE_name = ae.name
		else :
			for att_type in libmyCF.ontology.all_attributes_type : #Finding the attribute_type_id of the selected translation 
				if libmyCF.ontology.all_attributes_type[att_type].name == libmyCF.ontology.translation :
					att_type_id = libmyCF.ontology.all_attributes_type[att_type].attribute_type_id
					break
			for att in libmyCF.ontology.all_attributes : #finding the value of the attribute with the right att_type_id
				if att.attribute_type_id == att_type_id and att.AE_id ==ae.AE_id :
					AE_name = att.value
					break

		AE.__init__(self, libmyCF, ae.AE_id, AE_name, ae.definition, ae.source, ae.curator)
		self._updateText()
		
		#Color
		if ae.source:
			if str(ae.source[:3])=='FMA':
				color = QtGui.QColor(0,0,230,255)
				brush = QtGui.QBrush(color, QtCore.Qt.SolidPattern)
				self.setForeground(0, brush)
			if str(ae.source[:3])=='MCF':
				color = QtGui.QColor(255,100,0,255)
				brush = QtGui.QBrush(color, QtCore.Qt.SolidPattern)
				self.setForeground(0, brush)
    
	def _updateText(self): 
		self.setText( 0, QtCore.QString.fromUtf8( self.name))
        
class Iter(QtGui.QTreeWidgetItemIterator):
	def __init__(self, *args):
		QtGui.QTreeWidgetItemIterator.__init__(self, *args)
	def next(self):
		self.__iadd__(1)
		value = self.value()
		if value:
			return self.value()
		else:
			raise StopIteration
      
class MyCFTreeWidget(QtGui.QTreeWidget):
	"""A tree of AE from ontology """
    
	def __init__(self,parent, libmyCF):
		QtGui.QTreeWidget.__init__(self,parent)
		self.libmyCF= libmyCF
		self.setGeometry(QtCore.QRect(10,20,450,431))
		self.headerItem().setText(0,QtGui.QApplication.translate("MainWindow", "Ontology Entities", None, QtGui.QApplication.UnicodeUTF8))
		self.creatActions()
		self.creatMenus()
		#self.connect(self.action_new_EA, QtCore.SIGNAL("triggered()"), self.on_action_edit_EA_triggered)
        
	def creatActions(self):
		#Action Edit EA
	
		self.action_edit_EA=QtGui.QAction(self)
		if self.libmyCF.connector.access_mode == "write" and self.libmyCF.ontology.translation == "English translation" :
			self.action_edit_EA.setText("Edit AE")
		if self.libmyCF.connector.access_mode == "read" or self.libmyCF.ontology.translation != "English translation" :
			self.action_edit_EA.setText("View AE")
		self.action_edit_EA.setObjectName("action_edit_EA")
		if self.libmyCF.connector.access_mode == "read" or self.libmyCF.ontology.translation != "English translation" :
			self.action_edit_EA.setIcon(QtGui.QIcon("../ui/icons/db_status.png"))

		self.addAction(self.action_edit_EA)
		
		#Action New AE
		self.action_new_EA=QtGui.QAction(self)
		self.action_new_EA.setText("New AE")
		self.action_new_EA.setObjectName("action_new_EA")
		self.action_new_EA.setIcon(QtGui.QIcon("../ui/icons/db_add.png"))
		self.addAction(self.action_new_EA)
		
		#Action New relation
		self.action_new_relation=QtGui.QAction(self)
		self.action_new_relation.setText("New relation")
		self.action_new_relation.setObjectName("action_new_relation")
		self.action_new_relation.setIcon(QtGui.QIcon("../ui/icons/db_add.png"))
		self.addAction(self.action_new_relation)
		
		#Action create left and right children
		#self.action_create_LR_children=QtGui.QAction(self)
		#self.action_create_LR_children.setText("Create left-right children")
		#self.action_create_LR_children.setObjectName("action_create_LR_children")
		#self.addAction(self.action_create_LR_children)
		
		#Action Delete AE
		self.action_delete_EA=QtGui.QAction(self)
		self.action_delete_EA.setText("Delete AE")
		self.action_delete_EA.setObjectName("action_delete_EA")
		self.action_delete_EA.setIcon(QtGui.QIcon("../ui/icons/db_remove.png"))
		self.addAction(self.action_delete_EA)     
		
		#Expand Tree 1
		self.action_expand_tree_by_1=QtGui.QAction(self)
		self.action_expand_tree_by_1.setText("1")
		self.action_expand_tree_by_1.setObjectName("action_expand_tree_by_1")
		self.addAction(self.action_expand_tree_by_1)
		
		#Expand Tree 2
		self.action_expand_tree_by_2=QtGui.QAction(self)
		self.action_expand_tree_by_2.setText("2")
		self.action_expand_tree_by_2.setObjectName("action_expand_tree_by_2")
		self.addAction(self.action_expand_tree_by_2)        
		
		#Expand Tree 3
		self.action_expand_tree_by_3=QtGui.QAction(self)
		self.action_expand_tree_by_3.setText("3")
		self.action_expand_tree_by_3.setObjectName("action_expand_tree_by_3")
		self.addAction(self.action_expand_tree_by_3)
		
		#Expand Tree all
		self.action_expand_tree_all=QtGui.QAction(self)
		self.action_expand_tree_all.setText("all")
		self.action_expand_tree_all.setObjectName("action_expand_tree_all")
		self.addAction(self.action_expand_tree_all)
		
		#Collapse Tree
		self.action_collapse_tree=QtGui.QAction(self)
		self.action_collapse_tree.setText("Collapse Tree")
		self.action_collapse_tree.setObjectName("action_collapse_tree")
		self.addAction(self.action_collapse_tree)    
		
		QtCore.QMetaObject.connectSlotsByName( self)


	def creatMenus(self):
		self.contextmenu_EA= QtGui.QMenu()
		if self.libmyCF.connector.access_mode == "write" and self.libmyCF.ontology.translation == "English translation" :
			self.contextmenu_EA.addAction(self.action_new_EA)
		self.contextmenu_EA.addAction(self.action_edit_EA)
		if self.libmyCF.connector.access_mode == "write" and self.libmyCF.ontology.translation == "English translation" :
			self.contextmenu_EA.addAction(self.action_new_relation)
		# self.contextmenu_EA.addAction(self.action_create_LR_children)
		if self.libmyCF.connector.access_mode == "write" and self.libmyCF.ontology.translation == "English translation" :
			self.contextmenu_EA.addAction(self.action_delete_EA)
		
		self.contextmenu_EA.addSeparator()		
		self.expandmenu = QtGui.QMenu()
		self.expandmenu.addAction(self.action_expand_tree_by_1)
		self.expandmenu.addAction(self.action_expand_tree_by_2)
		self.expandmenu.addAction(self.action_expand_tree_by_3)
		self.expandmenu.addAction(self.action_expand_tree_all)
		self.expandmenu.setTitle("Expand Tree by  ")
		self.contextmenu_EA.addMenu(self.expandmenu)
		
		self.contextmenu_EA.addAction(self.action_collapse_tree)
 

        

	def contextMenuEvent(self,event):
		self.contextmenu_EA.exec_(event.globalPos())


	def reccur_expand(self, item, j):       
		if j > 0 :
			self.expandItem(item)
			i = 0
			nb_child = item.childCount()
			while i < nb_child:
				self.reccur_expand(item.child(i),j-1)
				i += 1


	def reccur_expand_all(self, item):       
		self.expandItem(item)
		i = 0
		nb_child = item.childCount()
		while i < nb_child:
			self.reccur_expand_all(item.child(i))
			i += 1

    
	def reccur_expand_inverse(self, item):       
		self.expandItem(item)
		if item.parent() :
			self.reccur_expand_inverse(item.parent())

    
	def reccur_collapse(self, item):       
		self.collapseItem(item)
		i = 0
		nb_child = item.childCount()
		while i < nb_child:
			self.reccur_collapse(item.child(i))
			i += 1
  
    
	@QtCore.pyqtSignature("bool")
	def on_action_expand_tree_by_1_triggered(self):
		if (self.currentItem()):
			self.reccur_expand(self.currentItem(), 1)   

            
	@QtCore.pyqtSignature("bool")
	def on_action_expand_tree_by_2_triggered(self):
		if (self.currentItem()):
			self.reccur_expand(self.currentItem(), 2) 

            
	@QtCore.pyqtSignature("bool")
	def on_action_expand_tree_by_3_triggered(self):
		if (self.currentItem()):
			self.reccur_expand(self.currentItem(), 3) 

            
	@QtCore.pyqtSignature("bool")
	def on_action_expand_tree_all_triggered(self):
		if (self.currentItem()):
			self.reccur_expand_all(self.currentItem()) 

    
	@QtCore.pyqtSignature("bool")
	def on_action_collapse_tree_triggered(self):
		if (self.currentItem()):
			self.reccur_collapse(self.currentItem())   

    
	@QtCore.pyqtSignature("bool")
	def on_action_edit_EA_triggered(self):
		"""Edit selected AE"""
		if (self.currentItem()):
			edit_dia = dialog_Edit_EA(self,self.currentItem(), self.relation_type_id, self.libmyCF)
			if edit_dia.exec_():
				#print "Update" 
				#self.currentItem().name = edit_dia.lineEdit_Name.text()
				#self.currentItem().definition = ( edit_dia.textEdit_definition.document().toPlainText()).encode( 'utf-8')
				#self.currentItem()._updateText()

				#self.ontology.get_all_AEs()
				self.refreshTree(self.relation_type_id)
				self.setCurrentItem(self.findItem(edit_dia.lineEdit_Name.text()))

	@QtCore.pyqtSignature("bool")
	def on_action_new_EA_triggered(self): 
		"""Create a new EA using the current EA as parent"""
		ndia = dialog_new_EA(self,self.currentItem(), self.relation_type_id, self.libmyCF)
		index = self.currentIndex()
		if ndia.exec_():

			#actualize the tree (old version) : reload the table of AEs from database and totally reconstruct the tree
			#self.ontology.get_all_AEs()
			#self.refreshTree(self.relation_type_id)
			#self.setCurrentItem(self.findItem(ndia.lineEdit_Latin_name.text()))

			#actualize the tree (new version) : faster
			print ndia.newAE
			newItem = MyCFTreeWidgetItem( self.libmyCF, ndia.newAE)
			self.currentItem().addChild(newItem)
			self.sortItems (0,QtCore.Qt.AscendingOrder)
			self.setCurrentItem(self.findItem(ndia.newAE.name))

	@QtCore.pyqtSignature("bool")
	def on_action_new_relation_triggered(self):
		"""create new relation with an existing EA using the current EA as parent"""
		new_rel_dia = dialog_new_relation(self,self.currentItem(), self.relation_type_id, self.libmyCF,None)
		if new_rel_dia.exec_() :
			#create the new relation
			self.libmyCF.ontology.add_relation( new_rel_dia.child[1], new_rel_dia.parent[1], new_rel_dia.selected_relation)
			if new_rel_dia.selected_relation == self.relation_type_id :
				# ACTUALIZE THE mCFTREE (old version) :
				#self.ontology.get_all_AEs()
				#self.refreshTree(self.relation_type_id)
				#self.setCurrentItem(self.findItem(str(new_rel_dia.child[0])))

				# ACTUALIZE THE mCFTREE (new version) : faster
				item_AE_id = new_rel_dia.child[1]
				item_name = new_rel_dia.child[0]  # = self.ontology.all_AEs[item_AE_id].name
				item_definition = self.ontology.all_AEs[item_AE_id].definition
				#if item already belongs to the current tree (i.e. has child(s) for the selected relation) and just has to be moved
				AE_relations = self.ontology.all_AEs[item_AE_id].get_l_relations()
				for relation in AE_relations :
					if relation.relation_type_id == self.relation_type_id  and relation.parent == item_AE_id :
						#self.setCurrentItem(self.findItem(str(new_rel_dia.parent[0])))
						#self.currentItem().addChild(self.findItem(item_name))
						#self.sortItems (0,QtCore.Qt.AscendingOrder)
						#self.setCurrentItem(self.findItem(item_name))
						self.refreshTree(self.relation_type_id)
						self.setCurrentItem(self.findItem(str(new_rel_dia.child[0])))
						return

				# if item does not appear in the current tree (i.e. does not have child for the selected relation)
				newItem = myCFTreeWidgetItem( self.libmyCF, item_AE_id, item_name, item_definition)
				self.setCurrentItem(self.findItem(str(new_rel_dia.parent[0])))
				self.currentItem().addChild(newItem)
				self.sortItems (0,QtCore.Qt.AscendingOrder)
				self.setCurrentItem(self.findItem(item_name))
				# ACTUALIZE THE mCFTREE (end)

	@QtCore.pyqtSignature("bool")
	def on_action_create_LR_children_triggered(self):
		"""create new left and right EA for a given EA"""
		#self.ontology.add_AE(self.AE_parent)
		QtGui.QMessageBox.information(self,"myCF information","Not implemented yet")
        
        
    
	@QtCore.pyqtSignature("bool")
	def on_action_delete_EA_triggered(self):
		"""Delete selected EA"""
		#QtGui.QMessageBox.information(self,"mCF information","Not yet implemented. Sorry")
		if len(self.currentItem().get_l_child(self.relation_type_id)) >0:
			QtGui.QMessageBox.warning(self,"myCF Error","This AE has child.\n You must remove its child first.")
			return
		answer = QtGui.QMessageBox.warning(self,"myCF : delete AE","Are you sure you want to delete the AE \'%s\' ?" % self.currentItem().name, QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
		
		if answer == QtGui.QMessageBox.Yes :
			item_to_delete = self.currentItem()
			#checking that the AE has not own attributes
			for att in self.libmyCF.ontology.all_attributes :
				if att.AE_id == item_to_delete.AE_id :
					QtGui.QMessageBox.warning(self,"myCF Error","The AE \'%s\' has its own attibrute(s).\nPlease delete those before." % item_to_delete.name)
					return
					
			for relation in self.libmyCF.ontology.all_relations :
				#checking that the AE is not implicated in other relation type
				if (relation.child == item_to_delete.AE_id or relation.parent == item_to_delete.AE_id) and relation.relation_type_id != self.relation_type_id :
					QtGui.QMessageBox.warning(self,"myCF Error","The AE \'%s\' is implicated in other relation types.\nIt will not be deleted." % item_to_delete.name)
					return				
				if relation.child == item_to_delete.AE_id and relation.relation_type_id == self.relation_type_id :
					parent_AE_id = relation.parent
			self.libmyCF.ontology.del_AE(item_to_delete.AE_id)
			self.setCurrentItem( self.findItem( self.libmyCF.ontology.all_AEs[parent_AE_id].name))
			self.currentItem().removeChild(item_to_delete)        

		

	def findItem(self,texte):
		"""Select the Item in the tree having the name 'texte'"""
		iterator = QtGui.QTreeWidgetItemIterator(self, QtGui.QTreeWidgetItemIterator.All)
		item = iterator.value()
		while item:
			if item.name == texte:  
				return item
			iterator += 1
			item = iterator.value()
		QtGui.QMessageBox.warning( self, "AE not found","The AE '" + texte + "' is not found")


	def refreshTree(self, relation_type_id):
		"""Update tree of EA"""
		self.clear()
		print ("building TreeWidget")
		self.relation_type_id= relation_type_id
		rootsAE = []
		child_dic = {}
		parent_dic = {}
		
		#initialize dictionaries
		for AE_id in self.libmyCF.ontology.all_AEs :
			child_dic[int(AE_id)]=[]
			parent_dic[int(AE_id)]=[]
		
		#get a dictionary of all AE_ids of child AE for an AE with its id as key of the dictionary
		for relation in  self.libmyCF.ontology.all_relations :			
			if relation.relation_type_id==relation_type_id:
				child_dic[int(relation.parent)].append(relation.child)
				parent_dic[int(relation.child)].append(relation.parent)
		
		#create all the roots (item with child and without parents)
		for key in parent_dic :
			if len(parent_dic[key])==0 and len(child_dic[key])>0 :
				rootsAE.append(self.libmyCF.ontology.all_AEs[key])
		
		processed_items = []  #AE already connected to the tree
		stack = []    #Stack of AE not connected to the tree, needing to be processed 
		for ae in rootsAE:
			# Create all the root items
			rootItem = MyCFTreeWidgetItem( self.libmyCF, ae)
			self.addTopLevelItem (rootItem)
			
			# Create the tree for this root item
			stack = [rootItem]
			while len( stack) > 0:
				# Get the child of the current item
				curItem = stack.pop()
#				for child in curItem.get_l_child(relation_type_id):
#					childItem = MyCFTreeWidgetItem( self.libmyCF, child)
#					curItem.addChild( childItem)
#					stack.append( childItem) 
				if not curItem.AE_id in processed_items :
					processed_items.append(curItem.AE_id)
					for child_id in child_dic[curItem.AE_id]:
						child_AE = self.libmyCF.ontology.all_AEs[child_id]
						childItem = MyCFTreeWidgetItem( self.libmyCF, child_AE)
						curItem.addChild( childItem)
						stack.append( childItem)
					#print("%d"%len(stack))
				else :
					print("AE %d = '%s' already processed"%(curItem.AE_id,curItem.name))
		self.sortItems (0,QtCore.Qt.AscendingOrder)